#include "fighter_michael.hpp"

using namespace Shiny;
using namespace Shiny::Applejack;

FighterMichael::FighterMichael(World& w, Body& b, Applejack::View* camera) : Player(w, b, camera)
{
    _damageResistance = 10;
    _speed            = 160;
    _strength         = 3;

    _isPhased         = false;
    _isShorty         = false;
    _isHacking        = false;

    _keyboard         = 0;
    _attackKeyboard   = new Attack(_keyboardCanHit, 0);
    _attackKeyboard->effects.push_back(Attack::Effect(Attack::Effect::STUN, 1000.f, 0.f));
    _attacks.push_back(_attackKeyboard);

    Shiny::TextureList* tex = _world.Hud()->GetTextureList();

    if (tex)
    {
	AddSpellDisplay(spell1, 0, (*tex)["spell-keyboard"]);
	AddSpellDisplay(spell2, 1, (*tex)["spell-dephased"]);
	AddSpellDisplay(spell3, 2, (*tex)["spell-gringalet"]);
	AddSpellDisplay(spell4, 3, (*tex)["spell-hacking"]);
    }
    
    Shiny::SoundList& sounds = _world.GetSounds();
    const sf::SoundBuffer*  spellHacking = sounds["spell-hacking"];
    const sf::SoundBuffer*  victory      = sounds["michael-victory"];

    if (spellHacking) _soundHacking.SetBuffer(*spellHacking);
    if (victory)      _soundVictory.SetBuffer(*victory);
    _soundHacking.SetLoop(true);
}

void FighterMichael::GetKicked(int damage, const Attack::Effects& effects)
{
    if (!_isPhased)
	Player::GetKicked(damage, effects);
}

void FighterMichael::InterruptChannelling()
{
    if (_isHacking)
	EndHacking();
}

void FighterMichael::SpellFirst(sf::Event)
{
  if (_cooldownKeyboardThrow.GetElapsedTime().AsSeconds() > CooldownKeyboardThrow)
  {
    sf::Vector2f throwPosition = _body.Sprite().GetPosition();
    Fixture*     fixture;
    b2Vec2       force;

    throwPosition.y -= 50.f;
    if (_lookingLeft)
    {
	force.Set(-40.f, 0.f);
	throwPosition.x -= 150.f;
    }
    else
    {
	force.Set(40.f, 0.f);
	throwPosition.x += 50.f;
    }
    _keyboardCanHit  = true;
    _keyboard        = Body::Factory::New(_world, "keyboard", throwPosition, 0.f);
    _keyboard->PhysicBody()->SetAngularVelocity(5.f);
    _keyboard->PhysicBody()->SetLinearVelocity(force);
    fixture          = _keyboard->Fixture("keyboard");
    _attackKeyboard->SetFixture(fixture);
    fixture->ContactEnd.Connect(*this, &FighterMichael::KeyboardDestroy);
    _cooldownKeyboardThrow.Restart();
  }
}

void FighterMichael::KeyboardDestroy(b2Contact*)
{
    _keyboardCanHit = false;
    _attackKeyboard->UnsetFixture();
    if (_keyboard)
      _keyboard->DeleteLater();
    _keyboard = 0;
}

void FighterMichael::SpellSecond(sf::Event)
{
    if (!_isPhased && _cooldownDephased.GetElapsedTime().AsSeconds() > CooldownPhase)
    {
	_body.Sprite().SetColor(sf::Color(255.f, 255.f, 255.f, 50.f));
	_isPhased = true;
	_cooldownDephased.Restart();
    }
}

void FighterMichael::SpellThird(sf::Event)
{
    if (!_isShorty && _cooldownGringalet.GetElapsedTime().AsSeconds() > CooldownShorty)
    {
	_isShorty                  = true;
	_speedModifier            += 100;
	_damageResistanceModifier -= _damageResistance / 2;
	_cooldownGringalet.Restart();
    }
}

void FighterMichael::SpellUltimate(sf::Event)
{
    if (!_isHacking && _cooldownHacking.GetElapsedTime().AsSeconds() > CooldownHacking)
    {
	if (_soundHacking.GetBuffer())
	  SoundManager::Get()->Play(&_soundHacking);
	_isHacking = true;
	_hackingTime.Restart();
    }
}

void FighterMichael::EndHacking(void)
{
    if (_soundHacking.GetBuffer())
      SoundManager::Get()->StopPlaying(&_soundHacking);
    _isHacking = false;
    _cooldownHacking.Restart();
}

void FighterMichael::ExecuteHacking(void)
{
    float time         = _hackingTime.GetElapsedTime().AsSeconds();
    float regainedLife = time * 60.f;

    _hackingTime.Restart();
    _life += regainedLife;
    if (_life > 100) _life = 100;
    LifeUpdated.Emit(_life);
}

void FighterMichael::Run(void)
{
    if (_isPhased && _cooldownDephased.GetElapsedTime().AsMilliseconds() > 500)
    {
	_body.Sprite().SetColor(sf::Color(255.f, 255.f, 255.f, 255.f));
	_isPhased = false;
	_cooldownDephased.Restart();
    }
    if (_isShorty && _cooldownGringalet.GetElapsedTime().AsSeconds() > 5)
    {
	_isShorty                  = false;
	_speedModifier            -= 100;
	_damageResistanceModifier += _damageResistance / 2;
    }
    if (_isHacking)
	ExecuteHacking();
    DisplaySpells();
    Player::Run();
}

void FighterMichael::DisplaySpells()
{
    UpdateSpellProgressBar(_cooldownKeyboardThrow.GetElapsedTime().AsSeconds(), CooldownKeyboardThrow, spell1);
    UpdateSpellProgressBar(_cooldownDephased.GetElapsedTime().AsSeconds(), CooldownPhase, spell2);
    UpdateSpellProgressBar(_cooldownGringalet.GetElapsedTime().AsSeconds(), CooldownShorty, spell3);
    UpdateSpellProgressBar(_cooldownHacking.GetElapsedTime().AsSeconds(), CooldownHacking, spell4);
}

void FighterMichael::Victory(bool hasWon)
{
  if (hasWon && _soundVictory.GetBuffer())
    SoundManager::Get()->Play(&_soundVictory);
  else if (!hasWon)
  {
    this->Stun(999999.f);
    delete _body.Fixture("body");
  }
}
